package com.cloudminds.resttest.api;

import com.cloudminds.resttest.cache.ConfigCache;
import com.cloudminds.resttest.helper.NewAsrHelper;
import com.cloudminds.resttest.helper.NewFrHelper;
import com.cloudminds.resttest.ice.AiasIceClient;
import com.cloudminds.resttest.ice.FrIceClient;
import com.cloudminds.resttest.mediatester.MediaTesterJni;
import com.cloudminds.resttest.push.PushClient;
import com.cloudminds.resttest.service.AppRTCClient;
import com.cloudminds.resttest.service.NewWebSocketChannelClient;
import com.cloudminds.resttest.vo.BaseResp;
import com.cloudminds.resttest.vo.CallParams;
import com.cloudminds.resttest.webrtc.SessionDescription;
import com.wordnik.swagger.annotations.ApiOperation;
import org.apache.commons.lang.StringUtils;
import org.json.JSONException;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Controller;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.net.URISyntaxException;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @Author syc
 * @Description //TODO $
 * @Date $ $
 **/
@Controller
//@RestController("/rest")
public class RestApi implements MediaTesterJni.MediaTesterEvent {
    private PushClient pushClient = null;
    private RestApi rest;
    private AppRTCClient.AssistantConnectionParameters assistantConnectionParameters;
    private Logger logger = LoggerFactory.getLogger(RestApi.class);
    private ConcurrentHashMap<String, String> hashMap = new ConcurrentHashMap<>(100);
    private static String rcuId = "A0-862851030073038";
    private static String Sid = null;
    private static FrIceClient frIceClient;
    MediaTesterJni mediaTesterJni ;
    long tester = -1;

    private static NewWebSocketChannelClient newWebSocketChannelClient = null;
    private static AiasIceClient aiasIceClient = null;
    @Value("${upload.temp.file.path}")
    private String uploadTempFilePath;

    private Object apiWaiter = new Object();

    public Object getApiWaiter(){
        return apiWaiter;
    }

    @ApiOperation("ConnectHari")
    @RequestMapping(value = "/ConnectHari", method = RequestMethod.POST)
    @ResponseBody
    public BaseResp ConnectHari(String username, String pwd, String tenantId, String appType, String serviceCode, String mqttUrl, String wsUrl, String iceGridLocator) throws JSONException, URISyntaxException {
        logger.info("----ConnectHari----");
        //连接hari
        BaseResp baseResponse = new BaseResp();
        JSONObject json = new JSONObject();
        ConfigCache configCache = ConfigCache.instance();

        ConfigCache.Config config = configCache.buildConfig(username, pwd, tenantId, appType, serviceCode, mqttUrl, wsUrl, iceGridLocator);

        if (!config.equals(configCache.getConfig())) {
            configCache.setConfig(config);

            // 重新初始化

            //			PushParams.setPushServer(config.getMqttUrl());
            //			PushClient.USERNAME = config.getUsername();
            //			PushClient.PASSWORD = config.getPwd();
            //
            //			CallParams.USER_NAME = config.getUsername();
            CallParams.TENANT_ID = config.getTenantId();
            //			CallParams.SERVICE_CODE = config.getServiceCode();

            newWebSocketChannelClient = new NewWebSocketChannelClient(new NewMessageReceiver());
            configCache.removeAyncMessage("login");
            AppRTCClient.AssistantConnectionParameters assistantConnectionParameters = new AppRTCClient.AssistantConnectionParameters();
            assistantConnectionParameters.rcuID = rcuId;

            newWebSocketChannelClient.setConnectionParameters(assistantConnectionParameters);

            newWebSocketChannelClient.connect(config.getWsUrl(), config.getUsername(), config.getPwd(), "");
        }

        if (newWebSocketChannelClient != null) {
            int i = 0;
            while (configCache.getAyncMessage("login") == null) {
                try {
                    //Thread.sleep(500);
                    synchronized (apiWaiter){
                        apiWaiter.wait(1000);
                    };
                } catch (InterruptedException e) {
                }
                if (i++ > 10) {
                    break;
                }
            }
            Sid = configCache.getAyncMessage("login").toString();
            aiasIceClient = new AiasIceClient();
            aiasIceClient.forceConnect();
            /*frIceClient= new FrIceClient();
            frIceClient.forceConnect();*/

            baseResponse.setData(json.put("sid",Sid).toString());
        } else {
            baseResponse.setData("parameter error!");
        }

        return baseResponse;
    }

    @ApiOperation("Say")
    @RequestMapping(value = "/Say", method = RequestMethod.POST)
    @ResponseBody
    public BaseResp Say(String sid, String question) {
        BaseResp baseResponse = new BaseResp();
        // JSONObject json = new JSONObject();
        try {
            if (aiasIceClient != null) {
                NewAsrHelper newAsrHelper = new NewAsrHelper(sid, aiasIceClient);
                newAsrHelper.startAsr1(sid, question);
            } else {
                baseResponse.setData("ice not init!");
            }

            ConfigCache configCache = ConfigCache.instance();
            int i = 0;

            while (configCache.getAyncMessage(sid + "_" + question) == null) {
                try {
                    synchronized (apiWaiter){
                        apiWaiter.wait(8000);
                    };
                    //Thread.sleep(800);
                } catch (InterruptedException e) {
                }

                if (i++ > 10) {
                    break;
                }
            }
           JSONObject json = (JSONObject) configCache.getAyncMessage(sid + "_" + question);
           JSONObject data = json.getJSONObject("data");
           JSONObject answer = (JSONObject) data.getJSONArray("answer").get(0);
           JSONObject tts =  (JSONObject) answer.getJSONArray("tts").get(0);
            System.out.print(tts+"=-=-=- tts -==-==-=-");
            baseResponse.setData(tts.toString());
        } catch (Exception e) {
            System.out.print(e);
        }
        // baseResponse.setData(json.toString());
        return baseResponse;
    }

    /*@ApiOperation("上传音频")
    @RequestMapping(value = "/uploadSpeechClip",method =RequestMethod.POST)
	public String SaySpeechClip(Model name)
	{
		name.addAttribute("type", "audios");
		return "upload";
	}*/

    //需要form 提交
    @ApiOperation("SaySpeechClip")
    @RequestMapping(value = "/SaySpeechClip", method = RequestMethod.POST)
    @ResponseBody
    public BaseResp SaySpeechClip(String sid, @RequestParam("file") MultipartFile file) throws IOException, JSONException {
        //
        BaseResp baseResponse = new BaseResp();
        //  JSONObject json = new JSONObject();
        String fileName = file.getOriginalFilename();// 文件原名称
        if (StringUtils.isNotBlank(file.getOriginalFilename())) {
            System.out.println("上传的文件原名称:" + fileName);
            String path = new File("").getAbsolutePath();
            //path = path + "/audios";
            //File f = new File(path+ "/audios");
            System.out.println("存放语音文件的路径:" + path);
            // 转存文件到指定的路径
            File dest = new File(new File(path+"/audios").getAbsolutePath()+ "/" + fileName);
            if (!dest.getParentFile().exists()) {
                dest.getParentFile().mkdirs();
            }else {
                delAllFile(path+"/audios");//先删除文件夹里面的文件
            }

           // file.transferTo(new File(path + "/" + fileName));
            file.transferTo(dest);
            System.out.println("文件成功上传到指定目录下");

            if (aiasIceClient != null) {
                NewAsrHelper newAsrHelper = new NewAsrHelper(sid, aiasIceClient);
                newAsrHelper.startAsr(sid);
            } else {
                baseResponse.setData("ice not init!");
            }
            ConfigCache configCache = ConfigCache.instance();
            int i = 0;
            while (configCache.getAyncMessage(sid +"_") == null) {
                try {

                    synchronized (apiWaiter){
                        apiWaiter.wait(8000);
                    };
                   // Thread.sleep(3000);
                } catch (InterruptedException e) {
                }
                if (i++ > 10) {
                    break;
                }
            }
            JSONObject json = (JSONObject) configCache.getAyncMessage(sid + "_");
            JSONObject data = json.getJSONObject("data");
            JSONObject answer = (JSONObject) data.getJSONArray("answer").get(0);
            JSONObject tts =  (JSONObject) answer.getJSONArray("tts").get(0);
            System.out.print(tts+"=-=-=- tts -==-==-=-");
            baseResponse.setData(tts.toString());
        } else {
            System.out.println("没有找到相对应的文件");
            return null;
        }

        return baseResponse;
    }

	/*@RequestMapping("/TriggerFaceEvent")
	public String TriggerFaceEvent(Model name)
	{
		name.addAttribute("type", "face");
		return "upload";
	}*/

   /* @ApiOperation("TriggerFaceEvent")
    @RequestMapping(value = "/TriggerFaceEvent", method = RequestMethod.POST)
    @ResponseBody
    public BaseResp TriggerFaceEvent(String sid, @RequestParam("file") MultipartFile face) throws IOException, JSONException {
        //调用人脸识别
        JSONObject json = new JSONObject();
        BaseResp baseResponse = new BaseResp();

        if (StringUtils.isNotBlank(face.getOriginalFilename())) {
            String fileName = face.getOriginalFilename();// 文件原名称
            System.out.println("上传的文件原名称:" + fileName);
            String path = new File("").getAbsolutePath();

            File dest = new File(new File(path+"/faces").getAbsolutePath()+ "/" + fileName);
            if (!dest.getParentFile().exists()) {
                dest.getParentFile().mkdirs();
            }else {
                delAllFile(path+"/faces");//先删除文件夹里面的文件
            }
            face.transferTo(dest);
            System.out.println("存放图片文件的路径:" + path);
            // 转存文件到指定的路径
          //  face.transferTo(new File(path + "/" + fileName));
            System.out.println("文件成功上传到指定目录下");

            *//* pushClient = new PushClient(rcuId);
              pushClient.connect();
             frIceClient = new FrIceClient();*//*

            //另一个 ice
            frIceClient = new FrIceClient();
            frIceClient.forceConnect();
            if (frIceClient != null) {
                NewFrHelper newFrHelper = new NewFrHelper(sid, frIceClient);
                newFrHelper.startFr(sid);
            } else {
                baseResponse.setData("ice not init!");
            }
            ConfigCache configCache = ConfigCache.instance();
            int i = 0;
            while (configCache.getAyncMessage(sid + "_fr") == null) {
                try {
                    synchronized (apiWaiter){
                        apiWaiter.wait(8000);
                    };
                    //Thread.sleep(3000);
                } catch (InterruptedException e) {
                }
                if (i++ > 10) {
                    break;
                }
            }

            baseResponse.setData(configCache.getAyncMessage(sid + "_fr").toString());

        } else {
            System.out.println("没有找到相对应的文件");
            return null;
        }

        json.put("sid", sid);
        baseResponse.setData(json.toString());
        return baseResponse;
    }*/


    @ApiOperation("SwitchHi")
    @RequestMapping(value = "/SwitchHi", method = RequestMethod.POST)
    @ResponseBody
    public BaseResp SwitchHi(String sid) throws InterruptedException, JSONException {
        JSONObject json = new JSONObject();
        BaseResp baseResponse = new BaseResp();
        if (sid!=""&sid!=null) {
            CallParams.VIDEO_ENABLE = true;
            logger.info("====VIDEO_ENABLE===状态"+CallParams.VIDEO_ENABLE);
            if (CallParams.VIDEO_ENABLE) {
                logger.info("=====初始化mediaTesterJni =====");
                mediaTesterJni = new MediaTesterJni();
                String state = connectMediaServer(sid);
                System.out.print("发起音视频状态" + state);
                json.put("sid", sid);
                json.put("state", state);
                baseResponse.setData(json.toString());
            }
        }
        return baseResponse;
    }

    @ApiOperation("DisconnectHari")
    @RequestMapping(value = "/DisconnectHari", method = RequestMethod.POST)
    @ResponseBody
    public BaseResp DisconnectHari(String sid) throws JSONException {
        JSONObject json = new JSONObject();
        BaseResp baseResponse = new BaseResp();
        stopCall(sid, newWebSocketChannelClient);
        //inst.closeWebSocket();
        json.put("sid", sid);
        json.put("tts", "断开连接");
        baseResponse.setData(json.toString());
        //tts
        if (sid!=""&&sid!=null)
        Sid = null;
        return baseResponse;
    }

    @ApiOperation("CheckAction")
    @RequestMapping(value = "/CheckAction", method = RequestMethod.POST)
    @ResponseBody
    public BaseResp CheckAction(String sid) {
        BaseResp baseResponse = new BaseResp();
        // JSONObject json = new JSONObject();
        try {
            if (aiasIceClient != null&&frIceClient!=null) {
                //  NewAsrHelper newAsrHelper = new NewAsrHelper(sid, aiasIceClient);
                // newAsrHelper.startAsr1(sid, info);
            } else {
                baseResponse.setData("ice not init!");
                return baseResponse;
            }

            ConfigCache configCache = ConfigCache.instance();
            //int i = 0;

            while (configCache.getAyncMessage(sid + "_CheckAction" ) == null) {
                try {
                    /*synchronized (apiWaiter){
                        apiWaiter.wait(30000);
                    };*/
                    Thread.sleep(30000);
                } catch (InterruptedException e) {
                }

               /* if (i++ > 10) {
                    break;
                }*/
            }
            baseResponse.setData(configCache.getAyncMessage(sid + "_CheckAction").toString());
        } catch (Exception e) {
            System.out.print(e);
        }
        // baseResponse.setData(json.toString());
        return baseResponse;
    }


    public void stopCall(String sid,NewWebSocketChannelClient newWebSocketChannelClient){
        System.out.println("StopCall entry");
        if (!sid.isEmpty()){
            newWebSocketChannelClient.logout(sid);
        }
        if (newWebSocketChannelClient != null) {
            newWebSocketChannelClient.disconnect(true);
            newWebSocketChannelClient = null;
        }
    }

    private String connectMediaServer(String sid){
        boolean justCreateWebrtc = false;
        String state ="";
        System.out.println("To create WebRTC if necessary...");
        mediaTesterJni.setMediaTesterEvent(this);
        String path = new File("").getAbsolutePath();
        tester = mediaTesterJni.CreateMediaTester(true,path+"/videos/rec-sample-video.mjr");
        String sdp = mediaTesterJni.GenerateSDP(tester);
        System.out.println("local sdp:"+sdp);
        if (!sdp.isEmpty()){
            SessionDescription ssdp = new SessionDescription(SessionDescription.Type.OFFER,sdp);
            state = newWebSocketChannelClient.sendCallStart(sid,ssdp);
            return state;
        }
        return state;
    }

    @Override
    public void onIceCandidate(String candidate) {

    }

    public static boolean delAllFile(String path) {
        boolean flag = false;
        File file = new File(path);
        if (!file.exists()) {
            return flag;
        }
        if (!file.isDirectory()) {
            return flag;
        }
        String[] tempList = file.list();
        File temp = null;
        for (int i = 0; i < tempList.length; i++) {
            if (path.endsWith(File.separator)) {
                temp = new File(path + tempList[i]);
            } else {
                temp = new File(path + File.separator + tempList[i]);
            }
            if (temp.isFile()) {
                temp.delete();
            }
            if (temp.isDirectory()) {
                delAllFile(path + "/" + tempList[i]);//先删除文件夹里面的文件
                flag = true;
            }
        }
        return flag;
    }

}